<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>设计模式——享元模式[优化Web日历]</title>
    <script type="application/javascript" charset="UTF-8" src="../../common/CommonUtils.js"></script>
    <script type="application/javascript" charset="UTF-8">
        // 享元模式：优化的设计模式 模拟Web日历
        // 年对象、月对象、天对象
        // 三者之间的关系就是，之间是包含的关系

        var Calendar = new WL.Interface(Calendar,['display']);

        // 年对象
        var CalendarYear = function (year,parent) {
            this.year = year;
            this.element = document.createElement('div');
            this.element.style['display'] = 'none'
            parent.appendChild(this.element);

            // 判断是否是闰年
            var isLeapYear = function (y) {
                return (y>0) && !(y%4) && ((y%100) || !(y%100));
            }


            // 保存当前年的每个月份的天数
            this.numDays = [31,isLeapYear(this.year)?29:28,31,30,31,30,30,31,30,31,30,31];
            // 年对象里应该包含月对象
            this.months = [];
            for (var i = 0; i < 12; i++) {
                this.months[i] = new CalendarMonth(i,this.numDays[i],this.element);
            }
        };

        // 实现接口方法
        CalendarYear.prototype = {
            constructor : CalendarYear,
            display : function () {
                for (var i = 0; i < this.months.length; i++) {
                    this.months[i].display();
                }
                this.element.style.display = 'block';
            }
        };

        // 月对象
        var CalendarMonth = function (monthNum,daysNum,parent) {
            this.monthNum = monthNum;
            this.element = document.createElement('div');
            this.element.style.display = 'none';
            parent.appendChild(this.element);

            // 月份对象里应该包含天对象
            this.days = [];
            for (var i = 0; i < daysNum; i++) {
                this.days[i] = daySingleInstance;
            }
        };

        // 月对象实现接口方法
        CalendarMonth.prototype = {
            constructor : CalendarMonth,
            display : function () {
                for (var i = 0; i < this.days.length; i++) {
                    this.days[i].display(i+1,this.element);
                }
                this.element.style.display = 'block';
            }
        };

        // 天对象
        var CalendarDay = function () {};

        // 天对象实现接口方法
        CalendarDay.prototype = {
            constructor : CalendarDay,
            display : function (date,parent) {
                var element = document.createElement('div');
                parent.appendChild(element);
                element.style.display = 'inline-block';
                element.innerHTML = date;
            }
        };

        // 单例对象
        var daySingleInstance = new CalendarDay();

        window.onload = function () {
            var myDiv = document.getElementById('mydiv');
            var myYear = new CalendarYear(2015,myDiv);
            myYear.display();
            // 这样存在一个问题
            // 假如现在实例化10年，每一年都要实例化12个月份，相当于实例化了120个月份对象
            // 更可怕的是，每一年需要实例化365个天对象，10年的话，就要实例化3650个天对象
            // 优化后，一年 12个月 1个天对象
        }
    </script>
</head>
<body>
<div id="mydiv"></div>
</body>
</html>